home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr46 / vfwdk.zip / VFWSDK.ZIP / SAMPLES / ICMAPP / ICMAPP.C < prev    next >
C/C++ Source or Header  |  1993-02-05  |  42KB  |  1,156 lines

  1. /*----------------------------------------------------------------------------*\
  2.  *
  3.  *  ICMAPP:
  4.  *
  5.  *    Sample app showing the use of DrawDib and the
  6.  *    VfW Image compression/decompression APIs
  7.  *
  8.  *    ICMAPP is a MDI aplication that demonstates the following:
  9.  *
  10.  *      - loading/saving windows bitmaps (ie DIBs) see DIB.C and DIB.H
  11.  *
  12.  *      - using DRAWDIB to draw compressed/uncompressed images
  13.  *
  14.  *      - calling ICCompressImage and ICDecompressImage
  15.  *
  16.  *    (C) Copyright Microsoft Corp. 1991, 1992, 1993.  All rights reserved.
  17.  *
  18.  *    You have a royalty-free right to use, modify, reproduce and
  19.  *    distribute the Sample Files (and/or any modified version) in
  20.  *    any way you find useful, provided that you agree that
  21.  *    Microsoft has no warranty obligations or liability for any
  22.  *    Sample Application Files.
  23.  *
  24.  *    If you did not get this from Microsoft Sources, then it may not be the
  25.  *    most current version.  This sample code in particular will be updated
  26.  *    and include more documentation.
  27.  *
  28.  *    Sources are:
  29.  *       CompuServe: WINSDK forum, MDK section.
  30.  *       Anonymous FTP from ftp.uu.net vendor\microsoft\multimedia
  31.  *
  32.  *----------------------------------------------------------------------------*/
  33.  
  34. #include <windows.h>
  35. #include <windowsx.h>
  36. #include <commdlg.h>
  37. #include <drawdib.h>
  38. #include <compman.h>
  39.  
  40. #include "icmapp.h"
  41. #include "dib.h"
  42. #include "icm.h"
  43.  
  44. static HCURSOR hcurSave;
  45. #define StartWait() hcurSave = SetCursor(LoadCursor(NULL,IDC_WAIT))
  46. #define EndWait()   SetCursor(hcurSave)
  47.  
  48. #define BOUND(x,min,max) ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x)))
  49. #define SWAP(x,y)   ((x)^=(y)^=(x)^=(y))
  50. #define ALIGNB(x)   (((x) + 7) & ~0x07)
  51.  
  52. #ifndef MKFOURCC
  53. #define MKFOURCC( ch0, ch1, ch2, ch3 )                                    \
  54.         ( (DWORD)(BYTE)(ch0) | ( (DWORD)(BYTE)(ch1) << 8 ) |    \
  55.         ( (DWORD)(BYTE)(ch2) << 16 ) | ( (DWORD)(BYTE)(ch3) << 24 ) )
  56. #endif
  57.  
  58. char    szAppName[]  ="ICMAPP";     /*  app's name */
  59. char    szDocClass[] ="ChildChild"; /*  the class of the child */
  60.  
  61. char    szOpenFilter[] = "Bitmaps\0*.dib;*.bmp;*.rle\0"
  62.                          "All\0*.*\0";
  63.  
  64. char    szSaveFilter[] = "Bitmaps\0*.dib;*.bmp;*.rle\0"
  65.                          "All\0*.*\0";
  66.  
  67. HANDLE  hInstApp;           /* Instance handle */
  68. HACCEL  hAccelApp;
  69. HWND    hwndApp;            /* Handle to parent window */
  70. HWND    hwndMdi;            /* Handle to MDI client window */
  71.  
  72. OFSTRUCT     of;
  73. OPENFILENAME ofn;
  74. char         achFileName[128];
  75.  
  76. static HANDLE CopyHandle(HANDLE h);
  77.  
  78. /*----------------------------------------------------------------------------*\
  79. \*----------------------------------------------------------------------------*/
  80.  
  81. long FAR PASCAL _export AppWndProc(HWND, UINT, WPARAM, LPARAM);
  82. long FAR PASCAL _export mdiDocWndProc(HWND, UINT, WPARAM, LPARAM);
  83. HWND mdiCreateDoc(LPSTR szClass, LPSTR szTitle, LPARAM l);
  84. int ErrMsg (LPSTR sz,...);
  85.  
  86. /*----------------------------------------------------------------------------*\
  87. |   AppAbout( hDlg, msg, wParam, lParam )                                      |
  88. |                                                                              |
  89. |   Description:                                                               |
  90. |       This function handles messages belonging to the "About" dialog box.    |
  91. |       The only message that it looks for is WM_COMMAND, indicating the use   |
  92. |       has pressed the "OK" button.  When this happens, it takes down         |
  93. |       the dialog box.                                                        |
  94. |                                                                              |
  95. |   Arguments:                                                                 |
  96. |       hDlg            window handle of about dialog window                   |
  97. |       msg             message number                                         |
  98. |       wParam          message-dependent                                      |
  99. |       lParam          message-dependent                                      |
  100. |                                                                              |
  101. |   Returns:                                                                   |
  102. |       TRUE if message has been processed, else FALSE                         |
  103. |                                                                              |
  104. \*----------------------------------------------------------------------------*/
  105. BOOL FAR PASCAL _export AppAbout(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  106. {
  107.     switch (msg)
  108.     {
  109.         case WM_COMMAND:
  110.             EndDialog(hwnd,TRUE);
  111.             return TRUE;
  112.  
  113.         case WM_INITDIALOG:
  114.         return TRUE;
  115.     }
  116.     return FALSE;
  117. }
  118.  
  119. /*----------------------------------------------------------------------------*\
  120. |   AppInit ( hInstance, hPrevInstance )                       |
  121. |                                                                              |
  122. |   Description:                                                               |
  123. |       This is called when the application is first loaded into               |
  124. |       memory.  It performs all initialization that doesn't need to be done   |
  125. |       once per instance.                                                     |
  126. |                                                                              |
  127. |   Arguments:                                                                 |
  128. |    hPrevInstance    instance handle of previous instance               |
  129. |       hInstance       instance handle of current instance                    |
  130. |                                                                              |
  131. |   Returns:                                                                   |
  132. |       TRUE if successful, FALSE if not                                       |
  133. |                                                                              |
  134. \*----------------------------------------------------------------------------*/
  135. BOOL AppInit(HANDLE hInst, HANDLE hPrev, LPSTR szCmd, int sw)
  136. {
  137.     WNDCLASS    cls;
  138.  
  139.     /* Save instance handle for DialogBox */
  140.     hInstApp = hInst;
  141.  
  142.     hAccelApp = LoadAccelerators(hInstApp, "AppAccel");
  143.  
  144.     if (!hPrev) {
  145.         cls.hCursor        = LoadCursor(NULL,IDC_ARROW);
  146.         cls.hIcon          = LoadIcon(hInst,"AppIcon");
  147.         cls.lpszMenuName   = "AppMenu";
  148.         cls.lpszClassName  = szAppName;
  149.         cls.hbrBackground  = (HBRUSH)COLOR_APPWORKSPACE+1;
  150.         cls.hInstance      = hInst;
  151.         cls.style          = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
  152.         cls.lpfnWndProc    = AppWndProc;
  153.         cls.cbClsExtra     = 0;
  154.     cls.cbWndExtra       = 0;
  155.  
  156.         if (!RegisterClass(&cls))
  157.             return FALSE;
  158.  
  159.         cls.hCursor        = LoadCursor(NULL,IDC_ARROW);
  160.         cls.hIcon          = LoadIcon(hInst,"DocIcon");
  161.         cls.lpszMenuName   = NULL;
  162.         cls.lpszClassName  = szDocClass;
  163.         cls.hbrBackground  = (HBRUSH)COLOR_WINDOW+1;
  164.         cls.hInstance      = hInst;
  165.         cls.style          = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
  166.         cls.lpfnWndProc    = mdiDocWndProc;
  167.         cls.cbClsExtra     = 0;
  168.     cls.cbWndExtra       = sizeof(LONG);
  169.  
  170.         if (!RegisterClass(&cls))
  171.             return FALSE;
  172.     }
  173.  
  174.     hwndApp = CreateWindow(szAppName,szAppName,
  175.            WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
  176.            CW_USEDEFAULT,0,
  177.            CW_USEDEFAULT,0,
  178.            (HWND)NULL,      /* no parent */
  179.            (HMENU)NULL,      /* use class menu */
  180.                (HANDLE)hInst,     /* handle to window instance */
  181.            (LPSTR)NULL      /* no params to pass on */
  182.          );
  183.  
  184.     /* Make window visible according to the way the app is activated */
  185.     ShowWindow(hwndApp,sw);
  186.  
  187.     if (szCmd && szCmd[0])
  188.         mdiCreateDoc(szDocClass, szCmd, 0);
  189.  
  190.     return TRUE;
  191. }
  192.  
  193. /*----------------------------------------------------------------------------*\
  194. |   WinMain( hInstance, hPrevInstance, lpszCmdLine, cmdShow )                  |
  195. |                                                                              |
  196. |   Description:                                                               |
  197. |       The main procedure for the App.  After initializing, it just goes      |
  198. |       into a message-processing loop until it gets a WM_QUIT message         |
  199. |       (meaning the app was closed).                                          |
  200. |                                                                              |
  201. |   Arguments:                                                                 |
  202. |       hInstance       instance handle of this instance of the app            |
  203. |       hPrevInstance   instance handle of previous instance, NULL if first    |
  204. |       lpszCmdLine     ->null-terminated command line                         |
  205. |       cmdShow         specifies how the window is initially displayed        |
  206. |                                                                              |
  207. |   Returns:                                                                   |
  208. |       The exit code as specified in the WM_QUIT message.                     |
  209. |                                                                              |
  210. \*----------------------------------------------------------------------------*/
  211. int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR szCmdLine, int sw)
  212. {
  213.     MSG     msg;
  214.  
  215.     if (!AppInit(hInstance,hPrevInstance,szCmdLine,sw))
  216.        return FALSE;
  217.  
  218.     /*
  219.      * Polling messages from event queue
  220.      */
  221.     for (;;)
  222.     {
  223.         if (PeekMessage(&msg, NULL, 0, 0,PM_REMOVE))
  224.         {
  225.             if (msg.message == WM_QUIT)
  226.                 break;
  227.  
  228.             if (hAccelApp && TranslateAccelerator(hwndApp, hAccelApp, &msg))
  229.                 continue;
  230.  
  231.             TranslateMessage(&msg);
  232.             DispatchMessage(&msg);
  233.         }
  234.         else
  235.         {
  236.             // idle time here, DONT BE A PIG!
  237.             WaitMessage();
  238.         }
  239.     }
  240.  
  241.     return msg.wParam;
  242. }
  243.  
  244. /*----------------------------------------------------------------------------*\
  245. \*----------------------------------------------------------------------------*/
  246.  
  247. BOOL fDialog(HWND hwnd,int id,FARPROC fpfn)
  248. {
  249.     BOOL    f;
  250.     HANDLE    hInst;
  251.  
  252.     hInst = GetWindowWord(hwnd,GWW_HINSTANCE);
  253.     fpfn  = MakeProcInstance(fpfn,hInst);
  254.     f = DialogBox(hInst,MAKEINTRESOURCE(id),hwnd,fpfn);
  255.     FreeProcInstance (fpfn);
  256.     return f;
  257. }
  258.  
  259. /*----------------------------------------------------------------------------*\
  260. \*----------------------------------------------------------------------------*/
  261.  
  262. #define mdiGetCreateParam(lParam) \
  263.  (((LPMDICREATESTRUCT)(((LPCREATESTRUCT)lParam)->lpCreateParams))->lParam)
  264.  
  265. /*----------------------------------------------------------------------------*\
  266. |   mdiCreateChild()                                   |
  267. |                                           |
  268. |   Description:                                                               |
  269. |                                                                              |
  270. |   Arguments:                                                                 |
  271. |                                                                              |
  272. |   Returns:                                                                   |
  273. |    HWND if successful, NULL otherwise                       |
  274. |                                           |
  275. \*----------------------------------------------------------------------------*/
  276.  
  277. HWND mdiCreateChild(
  278.     HWND  hwndMdi,
  279.     LPSTR szClass,
  280.     LPSTR szTitle,
  281.     DWORD dwStyle,
  282.     int   x,
  283.     int   y,
  284.     int   dx,
  285.     int   dy,
  286.     WORD  sw,
  287.     HMENU hmenu,
  288.     LPARAM l)
  289. {
  290.     MDICREATESTRUCT mdics;
  291.  
  292.     mdics.szClass   = szClass;
  293.     mdics.szTitle   = szTitle;
  294.     mdics.hOwner    = GetWindowWord(hwndMdi, GWW_HINSTANCE);
  295.     mdics.x         = x;
  296.     mdics.y         = y;
  297.     mdics.cx        = dx;
  298.     mdics.cy        = dy;
  299.     mdics.style     = dwStyle;
  300.     mdics.lParam    = l;
  301.  
  302.     return (HWND)SendMessage(hwndMdi,WM_MDICREATE,0,(LONG)(LPVOID)&mdics);
  303. }
  304.  
  305. /*----------------------------------------------------------------------------*\
  306. |   mdiCreateDoc()                                                           |
  307. |                                           |
  308. |   Description:                                                               |
  309. |                                                                              |
  310. |   Arguments:                                                                 |
  311. |                                                                              |
  312. |   Returns:                                                                   |
  313. |    HWND if successful, NULL otherwise                       |
  314. |                                           |
  315. |   Comments: We check the high word of the return value from WM_MDIGETACTIVE  |
  316. |   to determine whether we need to create the new window maximized or not.    |
  317. |                                           |
  318. \*----------------------------------------------------------------------------*/
  319.  
  320. HWND mdiCreateDoc(LPSTR szClass, LPSTR szTitle, LPARAM l)
  321. {
  322.     // Be sure to 
  323.     return mdiCreateChild(hwndMdi,szClass,szTitle,
  324.     HIWORD(SendMessage(hwndMdi, WM_MDIGETACTIVE, 0, 0L)) ? WS_MAXIMIZE: 0L,
  325.         CW_USEDEFAULT,0,CW_USEDEFAULT,0,SW_NORMAL,NULL,l);
  326. }
  327.  
  328. /*----------------------------------------------------------------------------*\
  329. |   mdiCreateClient()                                                           |
  330. |                                           |
  331. |   Description:                                                               |
  332. |                                                                              |
  333. |   Arguments:                                                                 |
  334. |                                                                              |
  335. |   Returns:                                                                   |
  336. |    HWND if successful, NULL otherwise                       |
  337. |                                           |
  338. \*----------------------------------------------------------------------------*/
  339. HWND FAR PASCAL mdiCreateClient(HWND hwndP, HMENU hmenuWindow)
  340. {
  341.     CLIENTCREATESTRUCT ccs;
  342.  
  343.     ccs.hWindowMenu = hmenuWindow;
  344.     ccs.idFirstChild = 10000;
  345.  
  346.     return CreateWindow ("MDICLIENT",NULL,
  347.                 WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,
  348.                 0,0,0,0,
  349.                 hwndP, 0, GetWindowWord(hwndP,GWW_HINSTANCE),
  350.                 (LPVOID)&ccs);
  351. }
  352.  
  353. /*----------------------------------------------------------------------------*\
  354. \*----------------------------------------------------------------------------*/
  355.  
  356. #define mdiActiveDoc(hwnd) \
  357.     (HWND)SendMessage(hwnd,WM_MDIGETACTIVE,0,0L)
  358.  
  359. /*----------------------------------------------------------------------------*\
  360. \*----------------------------------------------------------------------------*/
  361.  
  362. LONG NEAR PASCAL mdiSendMessage(HWND hwndMdi, HWND hwnd, unsigned msg, WORD wParam, LONG lParam)
  363. {
  364.     if (hwnd == (HWND)-1)
  365.     {
  366.         for (hwnd = GetWindow(hwndMdi, GW_CHILD); hwnd; hwnd = GetWindow(hwnd, GW_HWNDNEXT))
  367.             SendMessage(hwnd, msg, wParam, lParam);
  368.  
  369.         return 0L;
  370.     }
  371.     else
  372.     {
  373.         if (hwnd == NULL)
  374.             hwnd = mdiActiveDoc(hwndMdi);
  375.  
  376.         if (hwnd)
  377.             return SendMessage(hwnd, msg, wParam, lParam);
  378.     }
  379. }
  380.  
  381. /*----------------------------------------------------------------------------*\
  382. |   AppWndProc( hwnd, msg, wParam, lParam )                                    |
  383. |                                                                              |
  384. |   Description:                                                               |
  385. |       The window proc for the app's main (tiled) window.  This processes all |
  386. |       of the parent window's messages.                                       |
  387. |                                           |
  388. |   Arguments:                                                                 |
  389. |       hwnd            window handle for the parent window                    |
  390. |       msg             message number                                         |
  391. |       wParam          message-dependent                                      |
  392. |       lParam          message-dependent                                      |
  393. |                                                                              |
  394. |   Returns:                                                                   |
  395. |       0 if processed, nonzero if ignored                                     |
  396. |                                                                              |
  397. \*----------------------------------------------------------------------------*/
  398. long FAR PASCAL _export AppWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
  399. {
  400.     UINT            f;
  401.     PAINTSTRUCT     ps;
  402.     HDC             hdc;
  403.     HMENU           hmenu;
  404.     HANDLE          h;
  405.     HWND            hwndActive;
  406.  
  407.     switch (msg)
  408.     {
  409.     case WM_COMMAND:
  410.         switch(wParam)
  411.         {
  412.         case MENU_ABOUT:
  413.                     fDialog(hwnd,ABOUTBOX,(FARPROC)AppAbout);
  414.             break;
  415.  
  416.         case MENU_EXIT:
  417.                     PostMessage(hwnd,WM_CLOSE,0,0L);
  418.                     break;
  419.  
  420.                 case MENU_CLOSE:
  421.                     mdiSendMessage(hwndMdi,NULL,WM_CLOSE,0,0);
  422.                     break;
  423.  
  424.                 case MENU_CLOSEALL:
  425.                     while (hwndActive = mdiActiveDoc(hwndMdi))
  426.                         SendMessage(hwndActive,WM_CLOSE,0,0);
  427.                     break;
  428.  
  429.                 case MENU_PASTE:
  430.                     if (!OpenClipboard(hwnd))
  431.                         break;
  432.  
  433.                     if (h = GetClipboardData(CF_DIB))
  434.                         mdiCreateDoc(szDocClass,"Clipboard", CopyHandle(h));
  435.                     else if (h = GetClipboardData(CF_BITMAP))
  436.                         mdiCreateDoc(szDocClass,"Clipboard", DibFromBitmap(h, BI_RGB, 0, GetClipboardData(CF_PALETTE), 0));
  437.  
  438.                     CloseClipboard();
  439.                     break;
  440.  
  441.                 case MENU_NEW:
  442.                     mdiCreateDoc(szDocClass, "Untitled", 0);
  443.                     break;
  444.  
  445.                 case MENU_OPEN:
  446.                     /* prompt user for file to open */
  447.                     ofn.lStructSize = sizeof(OPENFILENAME);
  448.                     ofn.hwndOwner = hwnd;
  449.                     ofn.hInstance = NULL;
  450.                     ofn.lpstrFilter = szOpenFilter;
  451.                     ofn.lpstrCustomFilter = NULL;
  452.                     ofn.nMaxCustFilter = 0;
  453.                     ofn.nFilterIndex = 0;
  454.                     ofn.lpstrFile = achFileName;
  455.                     ofn.nMaxFile = sizeof(achFileName);
  456.                     ofn.lpstrFileTitle = NULL;
  457.                     ofn.nMaxFileTitle = 0;
  458.                     ofn.lpstrInitialDir = NULL;
  459.                     ofn.lpstrTitle = "Open";
  460.                     ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
  461.                     ofn.nFileOffset = 0;
  462.                     ofn.nFileExtension = 0;
  463.                     ofn.lpstrDefExt = NULL;
  464.                     ofn.lCustData = 0;
  465.                     ofn.lpfnHook = NULL;
  466.                     ofn.lpTemplateName = NULL;
  467.  
  468.                     if (GetOpenFileName(&ofn))
  469.                     {
  470.                         mdiCreateDoc(szDocClass, achFileName, 0);
  471.                     }
  472.                     break;
  473.  
  474.                 case WM_MDITILE:
  475.                 case WM_MDICASCADE:
  476.                 case WM_MDIICONARRANGE:
  477.                     SendMessage(hwndMdi, (UINT)wParam, 0, 0);
  478.                     break;
  479.  
  480.                 default:
  481.                     mdiSendMessage(hwndMdi,NULL,msg,wParam,lParam);
  482.                     break;
  483.         }
  484.             break;
  485.  
  486.         case WM_PALETTECHANGED:
  487.             return mdiSendMessage(hwndMdi, (HWND)-1, msg, wParam, lParam);
  488.  
  489.         case WM_QUERYNEWPALETTE:
  490.             return mdiSendMessage(hwndMdi, NULL, msg, wParam, lParam);
  491.  
  492.         case WM_INITMENU:
  493.  
  494.         f = (IsClipboardFormatAvailable(CF_DIB) ||
  495.         IsClipboardFormatAvailable(CF_BITMAP))
  496.         ? MF_ENABLED : MF_GRAYED;
  497.  
  498.         EnableMenuItem((HMENU)wParam, MENU_PASTE, f);
  499.  
  500.             hwndActive = mdiActiveDoc(hwndMdi);
  501.  
  502.             if(hwndActive)
  503.             {
  504.                 f = MF_ENABLED;
  505.                 EnableMenuItem((HMENU)wParam, MENU_CLOSE, f);
  506.                 EnableMenuItem((HMENU)wParam, MENU_CLOSEALL, f);
  507.                 SendMessage (hwndActive,msg,wParam,lParam);
  508.             }
  509.         else
  510.         {
  511.         f = MF_GRAYED;
  512.         EnableMenuItem((HMENU)wParam, MENU_CLOSE, f);
  513.                 EnableMenuItem((HMENU)wParam, MENU_CLOSEALL, f);
  514.         EnableMenuItem((HMENU)wParam, MENU_SAVE, f);
  515.                 EnableMenuItem((HMENU)wParam, MENU_COPY, f);
  516.                 EnableMenuItem((HMENU)wParam, MENU_COMPRESS, f);
  517.                 EnableMenuItem((HMENU)wParam, MENU_DECOMPRESS, f);
  518.  
  519.         }
  520.             break;
  521.  
  522.        case WM_CREATE:
  523.             hmenu = GetMenu(hwnd);
  524.             hwndMdi = mdiCreateClient(hwnd, GetSubMenu(hmenu, GetMenuItemCount(hmenu)-1));
  525.             break;
  526.  
  527.        case WM_SIZE:
  528.             MoveWindow(hwndMdi,0,0,LOWORD(lParam),HIWORD(lParam),TRUE);
  529.             break;
  530.  
  531.        case WM_DESTROY:
  532.         PostQuitMessage(0);
  533.         break;
  534.  
  535.        case WM_PAINT:
  536.             hdc = BeginPaint(hwnd, &ps);
  537.             EndPaint(hwnd, &ps);
  538.             return 0;
  539.     }
  540.     return DefFrameProc(hwnd,hwndMdi,msg,wParam,lParam);
  541. }
  542.  
  543. /*----------------------------------------------------------------------------*\
  544. \*----------------------------------------------------------------------------*/
  545. LPSTR FileName(LPSTR szPath)
  546. {
  547.     LPSTR   sz;
  548.  
  549.     #define SLASH(c)     ((c) == '/' || (c) == '\\')
  550.  
  551.     for (sz=szPath; *sz; sz++)
  552.         ;
  553.     for (; sz>=szPath && !SLASH(*sz) && *sz!=':'; sz--)
  554.         ;
  555.     return ++sz;
  556. }
  557.  
  558. /*----------------------------------------------------------------------------*\
  559. |   ErrMsg - Opens a Message box with a error message in it.  The user can     |
  560. |         select the OK button to continue or the CANCEL button to kill     |
  561. |         the parent application.                           |
  562. \*----------------------------------------------------------------------------*/
  563. int ErrMsg (LPSTR sz,...)
  564. {
  565.     char ach[128];
  566.     wvsprintf(ach,sz,(LPSTR)(&sz+1));   /* Format the string */
  567.     MessageBox (NULL,ach,NULL,MB_OK|MB_ICONEXCLAMATION);
  568.     return FALSE;
  569. }
  570.  
  571.  
  572. ///////////////////////////////////////////////////////////////////////////////
  573. ///////////////////////////////////////////////////////////////////////////////
  574. ///////////////////////////////////////////////////////////////////////////////
  575. ///////////////////////////////////////////////////////////////////////////////
  576. ///////////////////////////////////////////////////////////////////////////////
  577.  
  578. typedef struct
  579. {
  580.     HWND                hwnd;
  581.     HDRAWDIB            hdd;
  582.     HANDLE              hdib;
  583.     LPBITMAPINFOHEADER  lpbi;
  584.     BITMAPINFOHEADER    bi;
  585.     RECT                rcDraw;
  586.     RECT                rcSource;
  587.     int                 iZoom;
  588.     BOOL                fCanDecompress;
  589.     BOOL                fCanCompress;
  590.     char                achFileName[128];
  591. }   DIBINFO, *PDIBINFO;
  592.  
  593. void InitSize(PDIBINFO pdi);
  594. BOOL InitDib(PDIBINFO pdi, HANDLE hdib);
  595. void SizeWindowToImage(PDIBINFO pdi);
  596.  
  597. /*----------------------------------------------------------------------------*\
  598. |   mdiDocProc( hwnd, msg, wParam, lParam )                                    |
  599. |                                                                              |
  600. |   Description:                                                               |
  601. |    The window proc for a MDI child window                       |
  602. |                                           |
  603. |   Arguments:                                                                 |
  604. |       hwnd            window handle for the parent window                    |
  605. |       msg       message number                                               |
  606. |       wParam          message-dependent                                      |
  607. |       lParam          message-dependent                                      |
  608. |                                                                              |
  609. |   Returns:                                                                   |
  610. |       0 if processed, nonzero if ignored                                     |
  611. |                                                                              |
  612. \*----------------------------------------------------------------------------*/
  613.  
  614. long FAR PASCAL _export mdiDocWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  615. {
  616.     PDIBINFO        pdi;
  617.     UINT            f;
  618.     PAINTSTRUCT     ps;
  619.     HDC             hdc;
  620.     int             iMax;
  621.     int             iMin;
  622.     int             iPos;
  623.     int             dn;
  624.     RECT            rc;
  625.     LONG            lQuality;
  626.     HIC             hic;
  627.     HANDLE          hdib;
  628.  
  629.     pdi = (PDIBINFO)GetWindowLong(hwnd, 0);
  630.  
  631.     switch (msg)
  632.     {
  633.         case WM_CREATE:
  634.             pdi = (PDIBINFO)LocalAlloc(LPTR,sizeof(DIBINFO));
  635.             SetWindowLong(hwnd,0,(LONG)(UINT)pdi);
  636.  
  637.         if (pdi == NULL)
  638.         return -1;
  639.  
  640.             pdi->hwnd = hwnd;
  641.             GetWindowText(hwnd, pdi->achFileName, sizeof(pdi->achFileName));
  642.  
  643.             if (!InitDib(pdi, (HANDLE)mdiGetCreateParam(lParam)))
  644.         {
  645.                 ErrMsg("Unable to open '%s'",(LPSTR)pdi->achFileName);
  646.                 return -1;
  647.             }
  648.         break;
  649.                                                                  
  650.         case WM_SIZE:
  651.             InitSize(pdi);
  652.         break;
  653.  
  654.         case WM_CLOSE:
  655.             break;
  656.  
  657.         case WM_DESTROY:
  658.             if (pdi->hdib)
  659.                 GlobalFree(pdi->hdib);
  660.  
  661.             if (pdi->hdd)
  662.                 DrawDibClose(pdi->hdd);
  663.  
  664.         LocalFree((HLOCAL)pdi);
  665.         SetWindowLong(hwnd, 0, 0);
  666.             break;
  667.  
  668.         case WM_INITMENU:
  669.             f = pdi->hdib ? MF_ENABLED : MF_GRAYED;
  670.             EnableMenuItem((HMENU)wParam, MENU_COPY,  f);
  671.             EnableMenuItem((HMENU)wParam, MENU_SAVE,  f);
  672.  
  673.             EnableMenuItem((HMENU)wParam, MENU_DECOMPRESS, pdi->fCanDecompress ? MF_ENABLED : MF_GRAYED);
  674.             EnableMenuItem((HMENU)wParam, MENU_COMPRESS,   pdi->fCanCompress ? MF_ENABLED : MF_GRAYED);
  675.  
  676.             CheckMenuItem((HMENU)wParam, MENU_ZOOMW,   pdi->iZoom == 0      ? MF_CHECKED : MF_UNCHECKED);
  677.             CheckMenuItem((HMENU)wParam, MENU_ZOOM1,   pdi->iZoom == ZOOM   ? MF_CHECKED : MF_UNCHECKED);
  678.             CheckMenuItem((HMENU)wParam, MENU_ZOOM2,   pdi->iZoom == ZOOM*2 ? MF_CHECKED : MF_UNCHECKED);
  679.             CheckMenuItem((HMENU)wParam, MENU_ZOOM12,  pdi->iZoom == ZOOM/2 ? MF_CHECKED : MF_UNCHECKED);
  680.             break;
  681.  
  682.         case WM_COMMAND:
  683.             switch(wParam)
  684.             {
  685.                 case MENU_COMPRESS:
  686.  
  687.                     hic = NULL;
  688.                     lQuality = ICQUALITY_DEFAULT;
  689.  
  690.                     f = ICChooseCompressor(
  691.                                 hwnd,               // parent window for dialog
  692.                                 ICTYPE_VIDEO,       // compressor type to choose
  693.                                 0,                  // flags.
  694.                                 pdi->lpbi,          // input format (optional)
  695.                                 DibPtr(pdi->lpbi),  // input data (optional)
  696.                                 &hic,               // return HIC (caller must free)
  697.                                 &lQuality);         // return quality
  698.  
  699.                     if (f)
  700.                     {
  701.                         StartWait();
  702.  
  703.             UpdateWindow(hwndMdi);
  704.             
  705.                         hdib = ICCompressImage(
  706.                             hic,                // compressor to use
  707.                             0,                  // flags
  708.                             pdi->lpbi,          // format to compress from
  709.                             DibPtr(pdi->lpbi),  // bits to compress
  710.                             NULL,               // format to compress to. (default)
  711.                             lQuality);          // quality to use.
  712.  
  713.                         EndWait();
  714.  
  715.                         ICClose(hic);
  716.  
  717.                         if (hdib)
  718.                             mdiCreateDoc(szDocClass, pdi->achFileName, (LPARAM)(UINT)hdib);
  719.             else
  720.                 ErrMsg("Unable to compress DIB.");
  721.                     }
  722.                     break;
  723.  
  724.                 case MENU_DECOMPRESS:
  725.  
  726.                     StartWait();
  727.  
  728.                     hdib = ICDecompressImage(
  729.                             NULL,               // decompressor to use (any)
  730.                             0,                  // flags
  731.                             pdi->lpbi,          // format to decompress from
  732.                             DibPtr(pdi->lpbi),  // bits to decompress
  733.                             NULL,               // format to compress to. (any)
  734.                             0);                 // quality (not used)
  735.  
  736.                     EndWait();
  737.  
  738.                     if (hdib)
  739.                         mdiCreateDoc(szDocClass, pdi->achFileName, (LPARAM)(UINT)hdib);
  740.  
  741.                     break;
  742.             
  743.                 case MENU_ZOOM1:
  744.                 case MENU_ZOOM2:
  745.                 case MENU_ZOOM12:
  746.                 case MENU_ZOOMW:
  747.                     pdi->iZoom = (int)wParam - MENU_ZOOM;
  748.                     SizeWindowToImage(pdi);
  749.                     InvalidateRect(hwnd, NULL, TRUE);
  750.                     break;
  751.  
  752.                 case MENU_COPY:
  753.                     if (!OpenClipboard(hwnd))
  754.                         break;
  755.  
  756.                     EmptyClipboard();
  757.                     SetClipboardData(CF_DIB,CopyHandle(pdi->hdib));
  758.                     CloseClipboard();
  759.                     break;
  760.  
  761.                 case MENU_SAVE:
  762.                     lstrcpy(achFileName, pdi->achFileName);
  763.  
  764.                     /* prompt user for file to open */
  765.                     ofn.lStructSize = sizeof(OPENFILENAME);
  766.                     ofn.hwndOwner = hwnd;
  767.                     ofn.hInstance = NULL;
  768.                     ofn.lpstrFilter = szSaveFilter;
  769.                     ofn.lpstrCustomFilter = NULL;
  770.                     ofn.nMaxCustFilter = 0;
  771.                     ofn.nFilterIndex = 0;
  772.                     ofn.lpstrFile = achFileName;
  773.                     ofn.nMaxFile = sizeof(achFileName);
  774.                     ofn.lpstrFileTitle = NULL;
  775.                     ofn.nMaxFileTitle = 0;
  776.                     ofn.lpstrInitialDir = NULL;
  777.                     ofn.lpstrTitle = "Open Dib";
  778.                     ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
  779.                     ofn.nFileOffset = 0;
  780.                     ofn.nFileExtension = 0;
  781.                     ofn.lpstrDefExt = NULL;
  782.                     ofn.lCustData = 0;
  783.                     ofn.lpfnHook = NULL;
  784.                     ofn.lpTemplateName = NULL;
  785.  
  786.                     if (GetSaveFileName(&ofn))
  787.                     {
  788.                         WriteDIB(achFileName,pdi->hdib);
  789.                     }
  790.                     break;
  791.             }
  792.             break;
  793.  
  794.     case WM_KEYDOWN:
  795.             switch (wParam)
  796.             {
  797.                 case VK_UP:    PostMessage (hwnd,WM_VSCROLL,SB_LINEUP,0L);   break;
  798.                 case VK_DOWN:  PostMessage (hwnd,WM_VSCROLL,SB_LINEDOWN,0L); break;
  799.                 case VK_PRIOR: PostMessage (hwnd,WM_VSCROLL,SB_PAGEUP,0L);   break;
  800.                 case VK_NEXT:  PostMessage (hwnd,WM_VSCROLL,SB_PAGEDOWN,0L); break;
  801.  
  802.                 case VK_HOME:  PostMessage (hwnd,WM_HSCROLL,SB_PAGEUP,0L);   break;
  803.                 case VK_END:   PostMessage (hwnd,WM_HSCROLL,SB_PAGEDOWN,0L); break;
  804.                 case VK_LEFT:  PostMessage (hwnd,WM_HSCROLL,SB_LINEUP,0L);   break;
  805.                 case VK_RIGHT: PostMessage (hwnd,WM_HSCROLL,SB_LINEDOWN,0L); break;
  806.         }
  807.         break;
  808.  
  809.     case WM_KEYUP:
  810.             switch (wParam)
  811.             {
  812.            case VK_UP:
  813.            case VK_DOWN:
  814.            case VK_PRIOR:
  815.            case VK_NEXT:
  816.                   PostMessage (hwnd,WM_VSCROLL,SB_ENDSCROLL,0L);
  817.           break;
  818.  
  819.            case VK_HOME:
  820.            case VK_END:
  821.            case VK_LEFT:
  822.            case VK_RIGHT:
  823.                   PostMessage (hwnd,WM_HSCROLL,SB_ENDSCROLL,0L);
  824.           break;
  825.         }
  826.         break;
  827.  
  828.         case WM_VSCROLL:
  829.             GetScrollRange(hwnd,SB_VERT,&iMin,&iMax);
  830.             iPos = GetScrollPos(hwnd,SB_VERT);
  831.             GetClientRect(hwnd,&rc);
  832.  
  833.             switch (wParam)
  834.             {
  835.                 case SB_LINEDOWN:      dn =  rc.bottom / 16 + 1; break;
  836.                 case SB_LINEUP:        dn = -rc.bottom / 16 + 1; break;
  837.                 case SB_PAGEDOWN:      dn =  rc.bottom / 2  + 1; break;
  838.                 case SB_PAGEUP:        dn = -rc.bottom / 2  + 1; break;
  839.                 case SB_THUMBTRACK:
  840.                 case SB_THUMBPOSITION: dn = LOWORD(lParam)-iPos; break;
  841.                 default:               dn = 0;
  842.             }
  843.             if (dn = BOUND(iPos+dn,iMin,iMax) - iPos)
  844.             {
  845.                 ScrollWindow(hwnd,0,-dn,NULL,NULL);
  846.                 SetScrollPos(hwnd,SB_VERT,iPos+dn,TRUE);
  847.                 UpdateWindow(hwnd);
  848.             }
  849.             break;
  850.  
  851.         case WM_HSCROLL:
  852.             GetScrollRange(hwnd,SB_HORZ,&iMin,&iMax);
  853.             iPos = GetScrollPos(hwnd,SB_HORZ);
  854.             GetClientRect(hwnd,&rc);
  855.  
  856.             switch (wParam) {
  857.                 case SB_LINEDOWN:      dn =  rc.right / 16 + 1; break;
  858.                 case SB_LINEUP:        dn = -rc.right / 16 + 1; break;
  859.                 case SB_PAGEDOWN:      dn =  rc.right / 2  + 1; break;
  860.                 case SB_PAGEUP:        dn = -rc.right / 2  + 1; break;
  861.                 case SB_THUMBTRACK:
  862.                 case SB_THUMBPOSITION: dn = LOWORD(lParam)-iPos; break;
  863.                 default:               dn = 0;
  864.             }
  865.             dn = ALIGNB(dn);
  866.             if (dn = BOUND(iPos+dn,iMin,iMax) - iPos)
  867.             {
  868.                 ScrollWindow(hwnd,-dn,0,NULL,NULL);
  869.                 SetScrollPos(hwnd,SB_HORZ,iPos+dn,TRUE);
  870.                 UpdateWindow(hwnd);
  871.             }
  872.             break;
  873.  
  874.         case WM_CHILDACTIVATE:
  875.         case WM_ACTIVATE:
  876.             SendMessage(hwnd, WM_QUERYNEWPALETTE, 0, 0L);
  877.             break;
  878.  
  879.         case WM_PALETTECHANGED:
  880.             if (pdi == NULL || pdi->hdd == NULL)
  881.                 break;
  882.  
  883.             hdc = GetDC(hwnd);
  884.  
  885.             if (f = DrawDibRealize(pdi->hdd, hdc, TRUE))
  886.                 InvalidateRect(hwnd,NULL,TRUE);
  887.  
  888.             ReleaseDC(hwnd,hdc);
  889.  
  890.             return f;
  891.  
  892.         case WM_QUERYNEWPALETTE:
  893.             if (pdi == NULL || pdi->hdd == NULL)
  894.                 break;
  895.  
  896.             hdc = GetDC(hwnd);
  897.  
  898.             if (f = DrawDibRealize(pdi->hdd, hdc, FALSE))
  899.                 InvalidateRect(hwnd,NULL,TRUE);
  900.  
  901.             ReleaseDC(hwnd,hdc);
  902.  
  903.             return f;
  904.  
  905.     case WM_ERASEBKGND:
  906.         hdc = (HDC) wParam;
  907.             SaveDC(hdc);
  908.  
  909.             ExcludeClipRect(hdc,
  910.                 pdi->rcDraw.left,  pdi->rcDraw.top,
  911.                 pdi->rcDraw.right, pdi->rcDraw.bottom);
  912.  
  913.         DefWindowProc(hwnd, msg, wParam, lParam);
  914.  
  915.             RestoreDC(hdc, -1);
  916.             return 0L;
  917.  
  918.         case WM_PAINT:
  919.             hdc = BeginPaint(hwnd, &ps);
  920.  
  921.             if (pdi->hdib)
  922.             {
  923.                 SetWindowOrg(hdc,GetScrollPos(hwnd,SB_HORZ),GetScrollPos(hwnd,SB_VERT));
  924.  
  925.                 DrawDibRealize(pdi->hdd, hdc, TRUE);
  926.  
  927.                 f = DrawDibDraw(pdi->hdd,hdc,
  928.                     pdi->rcDraw.left,
  929.                     pdi->rcDraw.top,
  930.                     pdi->rcDraw.right -pdi->rcDraw.left,
  931.                     pdi->rcDraw.bottom-pdi->rcDraw.top,
  932.                     pdi->lpbi, NULL,
  933.                     pdi->rcSource.left,
  934.                     pdi->rcSource.top,
  935.                     pdi->rcSource.right -pdi->rcSource.left,
  936.                     pdi->rcSource.bottom-pdi->rcSource.top,
  937.                     DDF_SAME_HDC);
  938.  
  939.                 if (!f)
  940.                     FillRect(hdc, &pdi->rcDraw, GetStockObject(DKGRAY_BRUSH));
  941.             }
  942.  
  943.             EndPaint(hwnd, &ps);
  944.             return 0;
  945.     }
  946.     return DefMDIChildProc(hwnd,msg,wParam,lParam);
  947. }
  948.  
  949. /*----------------------------------------------------------------------------*\
  950. \*----------------------------------------------------------------------------*/
  951.  
  952. void GetRealClientRect(HWND hwnd, LPRECT lprc)
  953. {
  954.     DWORD dwStyle;
  955.  
  956.     dwStyle = GetWindowLong(hwnd,GWL_STYLE);
  957.     GetClientRect(hwnd,lprc);
  958.  
  959.     if (dwStyle & WS_HSCROLL)
  960.         lprc->bottom += GetSystemMetrics(SM_CYHSCROLL);
  961.  
  962.     if (dwStyle & WS_VSCROLL)
  963.         lprc->right  += GetSystemMetrics(SM_CXVSCROLL);
  964. }
  965.  
  966. void InitSize(PDIBINFO pdi)
  967. {
  968.     RECT rc;
  969.     int i,iRangeV,iRangeH;
  970.     static int iSem=0;
  971.  
  972.     if (pdi->hdib == NULL || iSem)
  973.         return;
  974.  
  975.     iSem++;
  976.  
  977.     //
  978.     // iZoom == 0 means stretch to window.
  979.     //
  980.     if (pdi->iZoom == 0 || IsIconic(pdi->hwnd)) {
  981.         SetScrollRange(pdi->hwnd,SB_VERT,0,0,TRUE);
  982.         SetScrollRange(pdi->hwnd,SB_HORZ,0,0,TRUE);
  983.         GetClientRect(pdi->hwnd, &pdi->rcDraw);
  984.     }
  985.     else {
  986.         SetRect(&pdi->rcDraw,0, 0,
  987.             (int)pdi->bi.biWidth * pdi->iZoom / ZOOM,
  988.             (int)pdi->bi.biHeight * pdi->iZoom / ZOOM);
  989.  
  990.         GetRealClientRect(pdi->hwnd,&rc);
  991.  
  992.         for (i=0; i<2; i++)
  993.         {
  994.             iRangeV = pdi->rcDraw.bottom - rc.bottom;
  995.             iRangeH = pdi->rcDraw.right - rc.right;
  996.  
  997.             if (iRangeH < 0) iRangeH = 0;
  998.             if (iRangeV < 0) iRangeV = 0;
  999.  
  1000.             if (GetScrollPos(pdi->hwnd,SB_VERT) > iRangeV ||
  1001.                 GetScrollPos(pdi->hwnd,SB_HORZ) > iRangeH)
  1002.                 InvalidateRect(pdi->hwnd,NULL,TRUE);
  1003.  
  1004.             SetScrollRange(pdi->hwnd,SB_VERT,0,iRangeV,TRUE);
  1005.             SetScrollRange(pdi->hwnd,SB_HORZ,0,iRangeH,TRUE);
  1006.  
  1007.             GetClientRect(pdi->hwnd,&rc);
  1008.         }
  1009.     }
  1010.  
  1011.     iSem--;
  1012. }
  1013.  
  1014. /*----------------------------------------------------------------------------*\
  1015. \*----------------------------------------------------------------------------*/
  1016.  
  1017. BOOL InitDib(PDIBINFO pdi, HANDLE hdib)
  1018. {
  1019.     char ach[80];
  1020.     DWORD dw;
  1021.     BOOL f;
  1022.  
  1023.     if (hdib == NULL)
  1024.         hdib = OpenDIB(pdi->achFileName);
  1025.  
  1026.     if (hdib == NULL)
  1027.         return FALSE;
  1028.  
  1029.     pdi->hdd   = DrawDibOpen();
  1030.     pdi->hdib  = hdib;
  1031.     pdi->iZoom = ZOOM;
  1032.     pdi->lpbi  = (LPVOID)GlobalLock(hdib);
  1033.     pdi->fCanCompress   = pdi->lpbi->biCompression == 0;
  1034.     pdi->fCanDecompress = pdi->lpbi->biCompression != 0;
  1035.  
  1036.     //
  1037.     //  fix up the default DIB fields
  1038.     //
  1039.     if (pdi->lpbi->biClrUsed == 0 && pdi->lpbi->biBitCount <= 8)
  1040.         pdi->lpbi->biClrUsed = (1 << (int)pdi->lpbi->biBitCount);
  1041.  
  1042.     f = DrawDibBegin(pdi->hdd,NULL,-1,-1,pdi->lpbi,-1,-1,0);
  1043.  
  1044.     if (!f)
  1045.         ErrMsg("Unable to draw this type of DIB");
  1046.  
  1047.     pdi->bi = *pdi->lpbi;
  1048.     SetRect(&pdi->rcSource,  0, 0, (int)pdi->bi.biWidth, (int)pdi->bi.biHeight);
  1049.  
  1050.     switch (dw = pdi->bi.biCompression)
  1051.     {
  1052.         case BI_RGB:    dw = mmioFOURCC('N', 'o', 'n', 'e'); break;
  1053.         case BI_RLE4:   dw = mmioFOURCC('R', 'l', 'e', '4'); break;
  1054.         case BI_RLE8:   dw = mmioFOURCC('R', 'l', 'e', '8'); break;
  1055.     }
  1056.  
  1057.     wsprintf(ach, "%ls (%dx%dx%d '%4.4ls' %dk)",
  1058.             FileName(pdi->achFileName),
  1059.             (int)pdi->bi.biWidth,
  1060.             (int)pdi->bi.biHeight,
  1061.             (int)pdi->bi.biBitCount,
  1062.             (LPSTR)&dw,
  1063.             (int)(pdi->bi.biSizeImage/1024));
  1064.  
  1065.     SetWindowText(pdi->hwnd, ach);
  1066.     SizeWindowToImage(pdi);
  1067.     return TRUE;
  1068. }
  1069.  
  1070. void SizeWindowToImage(PDIBINFO pdi)
  1071. {
  1072.     RECT rc;
  1073.     RECT rcMdi,rcChild;
  1074.  
  1075.     /* don't size window if it's currently maximized */
  1076.     if (!IsZoomed(pdi->hwnd) && !IsIconic(pdi->hwnd) && pdi->iZoom > 0)
  1077.     {
  1078.         SetRect(&rc, 0, 0,
  1079.             (int)pdi->bi.biWidth  * pdi->iZoom/ZOOM,
  1080.             (int)pdi->bi.biHeight * pdi->iZoom/ZOOM);
  1081.  
  1082.         AdjustWindowRect(&rc, GetWindowLong(pdi->hwnd, GWL_STYLE), FALSE);
  1083.  
  1084.     /* Determine size of MDI Client area and image window */
  1085.     GetClientRect(hwndMdi, &rcMdi);
  1086.     rc.right  -= rc.left;
  1087.     rc.bottom -= rc.top;
  1088.  
  1089.     /* Make sure window is positioned so that entire window is seen */
  1090.     GetWindowRect(pdi->hwnd, &rcChild);
  1091.     ScreenToClient(hwndMdi, (LPPOINT)&rcChild);
  1092.     if (rc.right > rcMdi.right)
  1093.     {
  1094.         rc.right = rcMdi.right+2;
  1095.         rcChild.left = -1;
  1096.     }
  1097.     if (rc.bottom > rcMdi.bottom)
  1098.     {
  1099.         rc.bottom = rcMdi.bottom+2;
  1100.         rcChild.top = -1;
  1101.     }
  1102.         SetWindowPos(pdi->hwnd, NULL,
  1103.             rcChild.left, rcChild.top, rc.right, rc.bottom,
  1104.             SWP_NOACTIVATE|SWP_NOZORDER);
  1105.     }
  1106.  
  1107.     InitSize(pdi);
  1108. }
  1109.  
  1110. static HANDLE CopyHandle(HANDLE h)
  1111. {
  1112.     HANDLE hCopy;
  1113.  
  1114.     if (hCopy = GlobalAlloc(GHND,GlobalSize(h)))
  1115.         hmemcpy(GlobalLock(hCopy), GlobalLock(h), GlobalSize(h));
  1116.  
  1117.     return hCopy;
  1118. }
  1119.  
  1120. /*****************************************************************************
  1121.  *
  1122.  * dprintf() is called by the DPF macro if DEBUG is defined at compile time.
  1123.  *
  1124.  * The messages will be send to COM1: like any debug message. To 
  1125.  * enable debug output, add the following to WIN.INI :
  1126.  *
  1127.  * [debug]
  1128.  * ICSAMPLE=1
  1129.  *
  1130.  ****************************************************************************/
  1131.  
  1132. #ifdef DEBUG
  1133.  
  1134. #define MODNAME "ICMAPP"
  1135.  
  1136. static void FAR cdecl dprintf(LPSTR szFormat, ...)
  1137. {
  1138.     char ach[128];
  1139.  
  1140.     static BOOL fDebug = -1;
  1141.  
  1142.     if (fDebug == -1)
  1143.         fDebug = GetProfileInt("Debug", MODNAME, FALSE);
  1144.  
  1145.     if (!fDebug)
  1146.         return;
  1147.  
  1148.     lstrcpy(ach, MODNAME ": ");
  1149.     wvsprintf(ach+lstrlen(ach),szFormat,(LPSTR)(&szFormat+1));
  1150.     lstrcat(ach, "\r\n");
  1151.  
  1152.     OutputDebugString(ach);
  1153. }
  1154.  
  1155. #endif
  1156.